﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace TerenXNA
{
    class CameraGround : Camera
    {
        private int przesx = 15, przesy = 1, przesz = 15;
        private float przesm = (float)0.01;

        public CameraGround(World world)
        {
            coords.world = world;
            starex = screenWidth / 2;
            starey = screenHeight / 2;
            this.cameraType = ScreenMenu.CameraType.Ground;
            loaded = true;
        }

        public CameraGround(Coords coords)
        {
            this.coords = coords;
            starex = screenWidth / 2;
            starey = screenHeight / 2;
            this.cameraType = ScreenMenu.CameraType.Ground;
            loaded = true;
        }

        // funkcje nadpisane z klasy kamera
        public override void keyUpdate(KeyboardState keyboardState)
        {
            base.keyUpdate(keyboardState);

            // turbo mode
            if (keyboardState.IsKeyDown(Keys.LeftShift))
            {
                przesx = przesz = 10;
            }
            else
            {
                przesx = przesz = 1;
            }

            if (keyboardState.IsKeyDown(Keys.W))
            {
                moveForward();
                heightUpdate();
            }
            if (keyboardState.IsKeyDown(Keys.S))
            {
                moveBackward();
                heightUpdate();
            }

            if (keyboardState.IsKeyDown(Keys.A))
            {
                moveLeft();
                heightUpdate();
            }
            if (keyboardState.IsKeyDown(Keys.D))
            {
                moveRight();
                heightUpdate();
            }
        }

        public override void mouseUpdate(MouseState mouseState)
        {
            base.mouseUpdate(mouseState);

            if (!this.paused)
            {
                //mysz
                int x = mouseState.X;
                int y = mouseState.Y;
                if (x != starex)
                {

                    patrzX(przesm * (starex - x));
                    starex = screenWidth / 2;
                    Mouse.SetPosition(screenWidth / 2, screenHeight / 2);
                }
                if (y != starey)
                {

                    patrzY(przesm * (starey - y) * aspectRatio);
                    starey = screenHeight / 2;
                    Mouse.SetPosition(screenWidth / 2, screenHeight / 2);
                }
            }
        }

        public override void heightUpdate()
        {
            if (coords.aktwx < 0 || coords.aktwz < 0 || coords.aktwx >= World.tilesX || coords.aktwz >= World.tilesY) return;
            try
            {
                coords.oby = coords.world.tiles[coords.aktwx, coords.aktwz].terrain.getHeight((int)coords.obx, (int)coords.obz) + 3;
            }
            catch
            {

            }
        }

        public override Vector3 getEye()
        {
            return new Vector3(coords.obx, coords.oby, coords.obz);
        }

        public override Vector3 getTarget()
        {
            return new Vector3(coords.obx + (float)Math.Sin(coords.kato) * 35, coords.oby + /*(float)Math.Sin(*/coords.katov/*)*/ * 20, coords.obz + (float)Math.Cos(coords.kato) * 35);
        }

        public override Vector3 getUp()
        {
            return new Vector3(0, 1, 0);
        }

        public override Matrix view()
        {
            return Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Game1.device.Viewport.AspectRatio, 1.0f, 9000.0f);
        }

        //funkcje wewnetrzne kamery
        public void patrzX(float f)
        {
            coords.kato = (float)(coords.kato + f);
        }

        public void patrzY(float f)
        {
            coords.katov = (float)(coords.katov + f);
            if (coords.katov > 4) coords.katov = (float)4;
            if (coords.katov < -4) coords.katov = (float)-4;
        }

        public void moveForward()
        {
            coords.obz = coords.obz + przesz * (float)Math.Cos(coords.kato);
            coords.obx = coords.obx + przesz * (float)Math.Sin(coords.kato);

            wspCheck();
        }

        public void moveBackward()
        {
            coords.obz = coords.obz - przesz * (float)Math.Cos(coords.kato);
            coords.obx = coords.obx - przesz * (float)Math.Sin(coords.kato);

            wspCheck();
        }

        public void moveLeft()
        {
            coords.obx = coords.obx + przesx * (float)Math.Cos(coords.kato);
            coords.obz = coords.obz - przesx * (float)Math.Sin(coords.kato);

            wspCheck();
        }

        public void moveRight()
        {
            coords.obx = coords.obx - przesx * (float)Math.Cos(coords.kato);
            coords.obz = coords.obz + przesx * (float)Math.Sin(coords.kato);

            wspCheck();
        }

        public void moveUp()
        {
            coords.oby += przesy;
        }

        public void moveDown()
        {
            coords.oby -= przesy;
        }

        public override void viewUpdate()
        {
            heightUpdate(); 
        }

        // bardzo istotna funkcja, trzeba pamietac ze
        // swiat sklada sie z 'kafelkow', wiec punkt 0
        // bedzie w rogu aktualnego pola, wiec trzeba
        // trzymac wspolrzedne w granicach tego pola
        public void wspCheck()
        {
            if (coords.obx <= 0)
            {
                coords.obx += (Tile.width - 1);
                coords.aktwx--; 
            }
            if (coords.obx >= (Tile.width - 1))
            {
                coords.obx -= (Tile.width - 1);
                coords.aktwx++; 
            }
            if (coords.obz <= 0)
            {
                coords.obz += (Tile.height - 1);
                coords.aktwz--; 
            }
            if (coords.obz >= (Tile.height - 1))
            {
                coords.obz -= (Tile.height - 1);
                coords.aktwz++;
            }
        }
    }
}
